package hn.sigit.logic.bpm;

import hn.sigit.model.ladm.administrative.LA_AdministrativeSource;
import hn.sigit.model.ladm.administrative.LA_AvailabilityStatusType;
import hn.sigit.model.ladm.external.ExtArchive;
import hn.sigit.util.AppOptions;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Date;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

public class ArchiveRepository {
	public static LA_AdministrativeSource addToRepository(AppOptions appOptions, AttachedFileData afd) {
		LA_AdministrativeSource newAdminSource = null;
		Date today = new Date();
		
		File fIn, fOut, fRepoDir, fOutDir;
		fIn = afd.getFile();
		if (fIn != null) {
			fRepoDir = new File(appOptions.getUploadFileSavePath());
			
			int nextFileIdx = countFilesInDir(fRepoDir) + 1;
			fOutDir = new File(appOptions.getUploadFileSavePath());
			
			if (!fOutDir.exists()) fOutDir.mkdirs();
			
			fOut = new File(fOutDir.getAbsolutePath() + '/' + String.format("%08d", nextFileIdx) + ".DAT");
			
			//TODO: DEFINIR POLITICA DE MANEJOR DE EXCEPCIONES
			try {
				copyFile(new FileInputStream(fIn), new FileOutputStream(fOut));
				afd.getFile().delete();
				afd.setFullPath(fOut.getCanonicalPath());
				
				newAdminSource = new LA_AdministrativeSource();
				newAdminSource.setAvailabilityStatus(LA_AvailabilityStatusType.ARCHIVE_CONVERTED);
				newAdminSource.setType(afd.getAdminSourceType());
				//newAdminSource.setAcceptance(today);
				newAdminSource.setRecordation(today);
				newAdminSource.setSubmission(today);
				
				ExtArchive extArchive = new ExtArchive();
				extArchive.setAcceptance(today);
				extArchive.setExternal(true);
				extArchive.setRecordation(today);
				extArchive.setSubmission(today);
				extArchive.setName(afd.getFileName());
				extArchive.setData(fOut.getName());
				extArchive.setDescription(afd.getDescripcion());
				
				newAdminSource.setArchive(extArchive);
				//adminSources.add(newAdminSource);
			}
			catch (FileNotFoundException fnfe) {
				FacesContext.getCurrentInstance().addMessage("oops",
						new FacesMessage("No se encontro un archivo"));
			}
			catch (IOException ioe) {
				FacesContext.getCurrentInstance().addMessage("oops",
						new FacesMessage("No se pudo adjuntar uno o mas archivos"));
			}
		}

		
		return newAdminSource;
	}
	
	private static void copyFile(FileInputStream sourceStream,
			FileOutputStream destinationStream) throws IOException {
		FileChannel inChannel = sourceStream.getChannel();
		FileChannel outChannel = destinationStream.getChannel();
		try {
			inChannel.transferTo(0, inChannel.size(), outChannel);
		} catch (IOException e) {
			throw e;
		} finally {
			if (inChannel != null) {
				try {
					inChannel.close();
				} catch (IOException ioe) {
				}
			}
			if (outChannel != null)
				outChannel.close();
		}
	}
	
	private static int countFilesInDir(File dir) {
		int count = 0;
		synchronized (ArchiveRepository.class) {
			if (dir.isDirectory()) {
				
				for (File file : dir.listFiles())
					if (file.isFile())
						count++;
			}
		}
		
		return count;
	}


}
